using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Data;
using System.Data.Entity.Infrastructure;
using ShopPowerTemplate.Services.Properties;
using ShopPowerTemplate.Entities;

namespace ShopPowerTemplate.Services
{
    public class ProductDetailServiceBase : Service
    {
		public ProductDetailServiceBase(IEntitiesDB entitiesDB) : base(entitiesDB) { }
		
        public virtual Int32 Add(ProductDetail productDetail)
        {
            productDetail.Product = EntitiesDB.EntryWithState(productDetail.Product, EntityState.Unchanged);
            EntitiesDB.ProductDetailSet.Add(productDetail);
            EntitiesDB.SaveChanges();
            return productDetail.Id;
        }

        public virtual void Change(ProductDetail productDetail)
        {
            productDetail.Product = EntitiesDB.EntryWithState(productDetail.Product, EntityState.Unchanged);
		    EntitiesDB.Entry(productDetail).State = EntityState.Modified;

            EntitiesDB.SaveChanges();
        }
		
		public virtual void Remove(int id)
        {
			ProductDetail productDetail = Find(id);
            try
            {
                EntitiesDB.ProductDetailSet.Remove(productDetail);
                EntitiesDB.SaveChanges();
            }
            catch (DbUpdateException)
            {
                throw new RemoveException(string.Format(Resources.RemoveException, productDetail.ToString()));
            }
        }

        public virtual void Remove(ProductDetail productDetail)
        {
			Remove(productDetail.Id);
        }        

        public virtual ProductDetail Find(int id)
        {
			ProductDetail productDetail = 
				EntitiesDB.ProductDetailSet
					.Include("Product")
					.Include("OrderDetails")
					.Include("Option.OptionType")
					.FirstOrDefault(x => x.Id == id);
			
			if(productDetail!=null)
			{
				var productAux = productDetail.Product; //EF4.1 bug hack
			}
			return productDetail;
        }

        public virtual List<ProductDetail> FindAll()
        {
            return EntitiesDB.ProductDetailSet.OrderBy(x => x.Id).ToList();
        }
		
		public virtual List<ProductDetail> Search(string searchValue)
        {
            return Search(searchValue, string.Empty, true, 0, 0);
        }

        public virtual List<ProductDetail> Search(string searchValue, int pageIndex, int pageSize)
        {
            return Search(searchValue, string.Empty, true, pageIndex, pageSize);
        }

        public virtual List<ProductDetail> Search(string searchValue, string orderBy)
        {
            return Search(searchValue, orderBy, true, 0, 0);
        }

        public virtual List<ProductDetail> Search(string searchValue, string orderBy, int pageIndex, int pageSize)
        {
            return Search(searchValue, orderBy, true, pageIndex, pageSize);
        }

        public virtual List<ProductDetail> Search(string searchValue, string orderBy = "", bool ascending = true, int pageIndex = 0, int pageSize = 10)
        {
            IQueryable<ProductDetail> query = EntitiesDB.ProductDetailSet;
			
			if(orderBy == string.Empty)
				orderBy = "Id";			
			
			query = ascending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);

            if (pageSize > 0)
                query = query.Skip(pageSize * pageIndex).Take(pageSize);

            return query.ToList();
        }
		
		public virtual List<ProductDetail> Search(Expression<Func<ProductDetail, bool>> searchCriteria, string orderBy = "", bool ascending = true, int pageIndex = 0, int pageSize=10)
        {
            IQueryable<ProductDetail> query = EntitiesDB.ProductDetailSet.Where(searchCriteria);
            
			if(orderBy == string.Empty)
				orderBy = "Id";			
			
			query = ascending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);

            if (pageSize > 0)
                query = query.Skip(pageSize * pageIndex).Take(pageSize);

            return query.ToList();
        }

        public virtual int SearchCount(string searchValue)
        {
            return EntitiesDB.ProductDetailSet.Count();
        }
		
		public virtual List<ProductDetail> FindAvailableProductDetailList<TKey>(List<ProductDetail> notAvailableList, string searchValue, System.Linq.Expressions.Expression<Func<ProductDetail, TKey>> orderBy, bool ascending, int pageIndex, int pageSize)
        {
            IEnumerable<int> notAvailableIDList = notAvailableList.Select(na => na.Id);
            IQueryable<ProductDetail> query = EntitiesDB.ProductDetailSet.Where(a => !notAvailableIDList.Any(id => id == a.Id));

			query = ascending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);

            if (pageSize > 0)
                query = query.Skip(pageSize * pageIndex).Take(pageSize);

            return query.ToList();
        }

        public virtual int FindAvailableProductDetailListCount(List<ProductDetail> notAvailableList, string searchValue)
        {
            IEnumerable<int> notAvailableIDList = notAvailableList.Select(na => na.Id);
            return EntitiesDB.ProductDetailSet.Where(a => !notAvailableIDList.Any(id => id == a.Id)).Count();
        }
	
		public virtual void AddOrderDetails(ProductDetail productDetail, OrderDetail orderDetails)
        {
			productDetail = Find(productDetail.Id);
            orderDetails.ProductDetail = productDetail;
            productDetail.OrderDetails.Add(orderDetails);
            orderDetails.Order = EntitiesDB.EntryWithState(orderDetails.Order, EntityState.Unchanged);

            Change(productDetail);
        }
		
		public virtual void RemoveOrderDetails(ProductDetail productDetail, OrderDetail orderDetails)
        {
            productDetail.OrderDetails.Remove(orderDetails);
			EntitiesDB.OrderDetailSet.Remove(orderDetails);			
            Change(productDetail);
        }

		public virtual void AddOption(ProductDetail productDetail, Option option)
        {
			productDetail = Find(productDetail.Id);
			option = EntitiesDB.OptionSet.Find(option.Id);

            option.ProductDetails.Add(productDetail);
            productDetail.Option.Add(option);

            Change(productDetail);
        }
		
		public virtual void RemoveOption(ProductDetail productDetail, Option option)
        {
			productDetail = Find(productDetail.Id);
			option = EntitiesDB.EntryWithState(option, EntityState.Unchanged);

            option.ProductDetails.Remove(productDetail);
            productDetail.Option.Remove(option);

            Change(productDetail);
        }
		
    }
}
